package com.zhj.rabbitmq.transaction;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @program: rabbimmq-demo
 * @description: rabbitmq 事务（transaction）模式发送消息
 * @author: zhengjibin
 * @create: 2020-11-18 11:34
 * @Version 1.0
 **/
public class TransactionSendMessage {
    public static void main(String[] args) {
        ConnectionFactory factory = new ConnectionFactory();
        //配置rabbitmq的链接信息
        factory.setHost("122.112.198.94");
        factory.setPort(5672);
        factory.setUsername("admin");
        factory.setPassword("admin");
        Connection connection = null;// 定义rabbitmq的网络连接 ，一个连接
        Channel channel = null;//定义一个链接中的通道
        try {
            connection = factory.newConnection();//通过工厂获得连接
            channel = connection.createChannel();//通过连接获得通道
            String queueName = "transaction_queue";
            String exchangeName = "transaction_exchange";
            String routingkey = "transactionRoutingKey";
            channel.queueDeclare(queueName,true,false,false,null);
            channel.exchangeDeclare(exchangeName,"direct",true);
            channel.queueBind(queueName,exchangeName,routingkey);
            String message = "事务(transaction)消息发送测试 第一条消息";

            //开启事务，开启事务后，不提交事务，消息就不会写入到队列中
            channel.txSelect();
            channel.basicPublish(exchangeName,routingkey,null,message.getBytes("UTF-8"));
            //如果不开启事务，那么第一条消息会发送到队列中，而第二条消息不会发送到队列中，这造成了消息的不完整
            //System.out.println(10/0); //分母为0会报错
            message = "事务(transaction)消息发送测试 第二条消息";
            channel.basicPublish(exchangeName,routingkey,null,message.getBytes("UTF-8"));

            //提交事务，提交事务后，才会将内存中(rabbitmq的一个区域)的数据真实的写入到队列中
            channel.txCommit();
            System.out.println("消息发送成功");
        } catch (IOException e) {
            System.out.println("消息发送失败");
            e.printStackTrace();
        } catch (TimeoutException e) {
            System.out.println("消息发送失败");
            e.printStackTrace();
        }finally {
            try {
                if (channel != null){
                    //在channel关闭之前回滚事务，将放弃所有没有提交的消息，释放内存
                    channel.txRollback();
                    channel.close();
                }
                if (connection != null){
                    connection.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }
    }
}
